﻿using System;
using System.Collections.Generic;
using System.Text;
using Slaks.Graphs.Category;
using System.Collections;

namespace Slaks.Graphs.Analysis
{
    public class IRAnalysis
    {
        public static double GetAvgPrecision(GraphList[] clusters, Category.CategoriesFile categoriesFile)
        {
            double precisionSum = 0d;
            int totalCount = 0;
            foreach (GraphList cluster in clusters)
            {
                var clusterPrecision = GetClusterPrecision(cluster, categoriesFile);
                precisionSum += clusterPrecision*cluster.Count;
                totalCount += cluster.Count;
            }
            return totalCount == 0? 0:precisionSum/totalCount;
        }
        public static double GetAvgRecall(GraphList[] clusters, CategoriesFile categoriesFile)
        {
            double recallSum = 0d;
            int totalCount = 0;
            foreach (GraphList cluster in clusters)
            {
                var clusterRecall = GetClusterRecall(cluster, categoriesFile);
                var freq = categoriesFile.CategoryFrequencyMap[cluster.GetCentroid().Category];
                recallSum += clusterRecall*freq;
                totalCount += freq;
            }
            return totalCount == 0 ? 0 : recallSum / totalCount;
        }
        public static double GetAvgFMesure(GraphList[] clusters, CategoriesFile categoriesFile)
        {
            double measureSum = 0d;
            int totalCount = 0;
            foreach (GraphList cluster in clusters)
            {
                var clusterRecall = GetClusterRecall(cluster, categoriesFile);
                var clusterPrecision = GetClusterPrecision(cluster, categoriesFile);
                var fmeasure = (2*clusterPrecision)/(clusterPrecision + clusterRecall);
                measureSum += fmeasure*cluster.Count;
                totalCount += cluster.Count;
            }
            return totalCount == 0 ? 0 : measureSum / totalCount;
        }

        public static double GetClusterRecall(GraphList cluster, CategoriesFile categoriesFile)
        {
            string selectedCategory = cluster.GetCentroid().Category;
            var relevantsFound=0d;
            foreach (Graph graph in cluster)
            {
                if (graph.Category == selectedCategory)
                {
                    relevantsFound++;
                }
            }
            return relevantsFound*1.0/cluster.Count;
        }

        public static double GetClusterPrecision(GraphList cluster, CategoriesFile file)
        {
            string selectedCategory = cluster.GetCentroid().Category;
            var relevantsFound=0;
            foreach (Graph graph in cluster)
            {
                if (graph.Category == selectedCategory)
                {
                    relevantsFound++;
                }
            }
            return relevantsFound*1.0/file.CategoryFrequencyMap[selectedCategory];
        }

        public static double GetAccuracy(Dictionary<Graph, string> resultsSet, CategoriesFile categoriesFile)
        {
            var correct = 0d;
            var retrieved = new Dictionary<string,IList<Graph>>();
            foreach (KeyValuePair<Graph, string> pair in resultsSet)
            {
                Graph graph = pair.Key;
                string category = pair.Value;
                if (graph.Category == category)
                {
                    correct++;
                }
                if(!retrieved.ContainsKey(category))
                {
                    retrieved[category] = new List<Graph>();
                }
                retrieved[category].Add(graph);
            }
            return correct * 1.0 / resultsSet.Count;
        }

        public static int GetNumberOfClustersIJ(GraphList[] clusters, IList categoryList, Document2CategoryMap document2categoryMap, int indexI, int indexJ)
        {
            int number = 0;

            string category = (string)categoryList[indexJ];
            string graphCategory;

            for (int i = 0; i < clusters[indexI].Count; i++)
            {
                graphCategory = (document2categoryMap == null) ? clusters[indexI][i].Category : (document2categoryMap[clusters[indexI][i].Name]);
                if (string.Equals(category, graphCategory)) ++number;
            }
            return number;
        }
    }
}